//
//  IFlyAudioPlayer.m
//  AIKITDemo
//
//  Created by xyzhang on 2023/3/1.
//
// 先处理非流式播放

#import "IFlyAudioPlayer.h"

#import <UIKit/UIKit.h>

#import "IFlyDebugLog.h"
#import "IFlyAudioSession.h"
#import "IFlyBufferQueue.h"

#define FRAME_COUNT         1024
#define AUDIO_BUFFERS       3           //音频队列的数据缓冲区大小
#define BUFFER_QUEUE_SIZE   100         //最大允许音频缓冲大小，单位MB
#define IFlyPlayerErrorDomain @"iflytek.IFlyAudioPlayer"

@interface IFlyAudioPlayer()

@property (nonatomic, assign) IFlyPlayerState state;

/// 错误码，播放器中的error对外都归类播放器错误（20011）
@property (nonatomic, assign) NSUInteger errorCode;

/// 系统打断导致的暂停播放
@property (nonatomic, assign) BOOL isSystemPaused;

@end

@implementation IFlyAudioPlayer

static dispatch_semaphore_t _sema; // 用于同步AQCallBack与freeAllRes操作，防止AQCallBack正在执行时（这个过程可能只有几毫秒），freeAllRes将AQCallBack访问的_aqc等资源释放
#pragma mark - public

+ (IFlyAudioPlayer *)sharedInstance {
    static IFlyAudioPlayer *instance = nil;
    static dispatch_once_t predict;
    dispatch_once(&predict, ^{
        instance = [[IFlyAudioPlayer alloc] init];
    });
    return instance;
}

- (instancetype)init {
    [IFlyDebugLog showLog:@"%s[IN],self=%d", __func__, self];
    self = [super init];
    if (self) {
        //关键参数放在对象生成时初始化
        _sampleRate = 16000;//默认采样率
        _bitDepth = 16;//默认位深度
        _soundTrack = IFLY_MONO;//默认单声道
        _state = IFlyPlayerStateEnd;//默认为结束状态
        
//        _aqc.queue = NULL;
//        _isRegisterRunningCB = NO;
//        _isPropertyRunning = NO;

//        _beginPos = 0;
//        _endPos = 0;
        
        //初始化播放器缓冲区
//        for (int i = 0; i < AUDIO_BUFFERS; i++){
//            _aqc.mBuffers[i] = NULL;
//            _aqc.mBuffersEmpty[i] = YES;
//        }
        
        //存放last数据段长度数组，每次播放完毕last都会回调onAudioQueueStop
//        _lastBuffLenArray = nil;
        
//        _addNewBuffer = YES;//初始需要新增数据段
        
//        _isAppendToPlayer = NO;
        
//        _stopCBQB = NULL;
        
//        if(IFlyPCMPlayerAQCallBackLocker == nil)
//        {
//            IFlyPCMPlayerAQCallBackLocker = [[NSLock alloc] init];//初始化锁
//        }
        
//        _playMode = MODE_NORMAL;
        
//        _isNeedDeActive = YES;
        
        _sema = dispatch_semaphore_create(1); //初始化信号量
    }
    [IFlyDebugLog showLog:@"%s[OUT],self=%d",__func__,self];
    return self;
}

- (void)dealloc {
    [IFlyDebugLog showLog:@"%s[IN],self=%d",__func__,self];
    [self freePlayerAllRes];
    [IFlyDebugLog showLog:@"%s[OUT],self=%d",__func__,self];
}

#pragma mark player

- (BOOL)play {
    @synchronized (self) {
        [IFlyDebugLog showLog:@"%s,[IN],self=%d", __func__, self];
        
        if(_state != IFlyPlayerStateEnd){
            return NO;
        }
        
        if(_delegate == nil){
            return NO;
        }
        
        if(![self initPlayerAllRes]){
            return NO;
        }
        
        BOOL ret = [self startAudioQueue];//初始化播放器
        
        if(!ret){
            return NO;
        }
        
        //初始为初始化状态, 设置IFlyPlayerStateInit状态需要在初始化播放器之后，避免过早进入AQBufferCallBack，因为此时尚无数据
        [self setPlayerState:IFlyPlayerStateInit];
        
        [IFlyDebugLog showLog:@"%s[OUT],self=%d",__func__,self];
        
        return YES;
    }
}

#pragma mark - private

/*
 初始化播放器运行参数
 */
- (BOOL)initPlayerAllRes {
    [IFlyDebugLog showLog:@"%s,[IN],self=%d", __func__, self];
    
    if(_state != IFlyPlayerStateEnd){
        [IFlyDebugLog showLog:@"%s,[OUT],_state=%d", __func__, _state];
        return NO;
    }
    
    [IFlyDebugLog showLog:@"%s,[OUT]",__func__];
    return YES;
}

- (void)freePlayerAllRes {
    
}

- (BOOL)startAudioQueue {
    [IFlyDebugLog showLog:@"%s,self=%d[IN]",__func__,self];
    
    if(_state != IFlyPlayerStateEnd){
        [IFlyDebugLog showLog:@"%s,[OUT],_state=%d",__func__,_state];
        return NO;
    }
    
    BOOL success;
    OSStatus error;
    NSError * setCategoryError;
    
    AVAudioSession *session = [AVAudioSession sharedInstance];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(interruption:) name:AVAudioSessionInterruptionNotification object:nil];
    
    success = [session setActive:YES error:&setCategoryError];
    if (!success){
        [IFlyDebugLog showLog:@"%s| session activate error:@%", __func__, setCategoryError];
    }
    
    // $$$$$ 初始化AudioQueue
    
    [IFlyDebugLog showLog:@"%s,self=%d[OUT]", __func__, self];
    return YES;
}


/// 设置pcm播放器的状态
/// - Parameter state: IFlyPlayerState
- (void)setPlayerState:(IFlyPlayerState)state {
    @synchronized(self) {
        
        if(_state == state){
            return;
        } else {
            _state = state;
        }
        
        if(IFlyPlayerStateEnd == state){
            [IFlyDebugLog showLog:@"%s,IFlyPlayerStateEnd,delegate =%d", __func__, _delegate];
        }
    
        switch (state) {
            case IFlyPlayerStateInit:
                break;
            case IFlyPlayerStatePlaying:
            {
                if (_delegate && [_delegate respondsToSelector:@selector(onIFlyPlayerPlay)]) {
                    [_delegate onIFlyPlayerPlay];
                }
            }
                break;
            case IFlyPlayerStateBuffer:
            {
                [IFlyDebugLog showLog:@"%s,state=%d", __func__, IFlyPlayerStateBuffer];
                if (_delegate && [_delegate respondsToSelector:@selector(onIFlyPlayerPause)]){
                    [_delegate onIFlyPlayerPause];
                }
            }
                break;
            case IFlyPlayerStatePause:
            {
                [IFlyDebugLog showLog:@"%s,state=%d", __func__, IFlyPlayerStatePause];
                if (_delegate && [_delegate respondsToSelector:@selector(onIFlyPlayerPause)]){
                    [_delegate onIFlyPlayerPause];
                }
            }
                break;
            case IFlyPlayerStateResume:
            {
                [IFlyDebugLog showLog:@"%s,state=%d",__func__,IFlyPlayerStateResume];
                if (_delegate && [_delegate respondsToSelector:@selector(onIFlyPlayerResume)]){
                    [_delegate onIFlyPlayerResume];
                }
            }
                break;
            case IFlyPlayerStateCancel:
                break;
            case IFlyPlayerStateEnd:
            {
                //抛出结束回调需要谨慎，一定要确保音频处于终止状态
                //避免出现播放器被释放，但是系统播放器仍然抛出回调造成崩溃
                [IFlyDebugLog showLog:@"%s,state=%d", __func__, IFlyPlayerStateEnd];
                
                //释放播放器所占资源
                [self freePlayerAllRes];
                
                //播放器终止，向系统注册deactive消息
                [[AVAudioSession sharedInstance] setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:NULL];
                
                if (_delegate && [_delegate respondsToSelector:@selector(onIFlyPlayerStop:)]){
                    NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[self errorDesc:_errorCode] forKey:NSLocalizedDescriptionKey];
                    
                    [_delegate onIFlyPlayerStop:[NSError errorWithDomain:IFlyPlayerErrorDomain code:_errorCode userInfo:userInfo]];
                }
                _delegate = nil;
            }
                break;
            default:
                break;
        }
    }
}

/// 播放器错误描述
/// - Parameter errorCode: 错误码
- (NSString *)errorDesc:(NSInteger)errorCode {
    
    NSString *desc;
    switch(errorCode){
        case 0:
            desc = @"No Error";
            break;
        case 1:
            desc = @"AudioQueueAllocateBuffer Error";
            break;
        case 2:
            desc = @"AudioQueueStart Error";
            break;
        case 3:
            desc = @"FilledAudioBuffer Error";
            break;
        default:
            desc = @"Unknown Error";
            break;
    }
    
    return desc;
}

#pragma mark interruption

/// 解除播放器回调
- (void)removeNotification {
    [IFlyDebugLog showLog:@"%s", __func__];
    [[NSNotificationCenter defaultCenter] removeObserver:self  name:AVAudioSessionInterruptionNotification object:nil];
}

/// 系统中断入口
- (void)beginInterruption {
    @synchronized(self) {
//        [IFlyDebugLog showLog:@"%s,_state=%d",__func__,_state];
        if(_state == IFlyPlayerStateEnd || _state == IFlyPlayerStateCancel){
            return;
        }
        
        if(_state != IFlyPlayerStatePause){
            [self pause];
            //中断结束时需要resume
            _isSystemPaused = YES;
        }
    }
}

/// 系统中断结束
- (void)endInterruption {
    @synchronized(self) {
        [IFlyDebugLog showLog:@"%s,_isSystemPaused=%d,_state=%d", __func__, _isSystemPaused,_state];
        
        if (_state == IFlyPlayerStateEnd || _state == IFlyPlayerStateCancel){
            return;
        }
        
        if (_state == IFlyPlayerStatePause && _isSystemPaused){
            [self resume];
        }
        
        _isSystemPaused = NO;
    }
}

/**
 @描述：系统中断通知总入口
 */
- (void)interruption:(NSNotification *)noti {
    [IFlyDebugLog showLog:@"%s",__func__];
    
    NSDictionary *interuptionDict = noti.userInfo;
    
    NSNumber *interuptionType = (NSNumber *)[interuptionDict valueForKey:AVAudioSessionInterruptionTypeKey];
    
    if ([interuptionType intValue] == AVAudioSessionInterruptionTypeBegan) {
        [self beginInterruption];
    }
    else if ([interuptionType intValue] == AVAudioSessionInterruptionTypeEnded) {
        [self endInterruption];
    }
}

@end
